home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGSCAL / EXTMEM.LZH / EXTMEM.DOC next >
Text File  |  1987-09-17  |  9KB  |  167 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.                               Accessing Extended Memory
  8.                             from Turbo C and Turbo Pascal
  9.  
  10.                "Extended memory" refers to the memory at addresses above
  11.           the 1 Megabyte that DOS can handle.  It is only available on the
  12.           AT and compatibles and the XT-286.  The PC and the XT do not have
  13.           extended memory.
  14.                In order to access extended memory, you must first determine
  15.           that there is, in fact, extended memory present, and the amount
  16.           of extended memory present.  This is done through BIOS interrupt
  17.           15H, function 88H.  On return, the carry flag will be set if an
  18.           error occurred (for instance, if the program is running on a PC,
  19.           where function 88H isn't supported).  If the carry flag is
  20.           cleared on return, then register AX contains the number of
  21.           kilobytes of extended memory present in the system.
  22.                One caution on detecting extended memory: technically, as I
  23.           understand it, your program should also check that the switches
  24.           on the extended memory board have been set so that the board will
  25.           back-fill main memory out to 640K, and only use the remainder for
  26.           extended memory.  I don't know what happens if you haven't set
  27.           the switches this way, and I haven't been able to get the test
  28.           for the switch settings to work.  Anybody who wants to poke into
  29.           VDISK.LST and sort it out is welcome to.
  30.                Once you've determined the amount of extended memory
  31.           present, you still have to figure out if any other program (such
  32.           as a RAMDISK) is using extended memory.  There is no system-level
  33.           memory manager for extended memory, so it's up to each program to
  34.           talk to any other programs and sort out their own allocations. 
  35.           Ordinarily, all you'll have to worry about is device drivers like
  36.           VDISK.  In fact, the only program I know how to detect is VDISK.
  37.                When VDISK is installed, it takes over interrupt 19H, which
  38.           is invoked during a boot to load MS-DOS from your boot disk.  The
  39.           only reason it does this is so that later installations of VDISK
  40.           can tell that they're not the first.  The only processing that
  41.           VDISK does on an int 19H call is to restore the original
  42.           interrupt vector and jump to that routine.
  43.                The benefit of redirecting interrupt 19H is that the jump
  44.           vector for interrupt 19H can be used to find where VDISK is
  45.           installed.  The segment where VDISK is located is found in the
  46.           second word of the interrupt 19H vector.  The address of that
  47.           word is 0000:0066.  Take the word located at that address as the
  48.           segment of VDISK.
  49.                To actually detect the presence of VDISK, your program has
  50.           to check offset 12H within the segment where VDISK is located. 
  51.           Beginning at that location VDISK will contain the character
  52.           string "VDISK  V3.2".  (Note -- two spaces between VDISK and
  53.           V3.2).  If that string isn't present, VDISK isn't installed and
  54.           all of extended memory is available to your program.
  55.                If VDISK is installed, the address of the first available
  56.           location in extended memory is stored at offsets 2CH, 2DH, and
  57.           2EH in the segment where VDISK is located.  Just grab those three
  58.           bytes and save them somewhere.  If VDISK isn't installed, the
  59.           first available location in extended memory is 100000H.
  60.                Once you know where available extended memory begins, you
  61.  
  62.  
  63.  
  64.  
  65.  
  66.           can figure out exactly how much space is available for your
  67.           program to use.  Just subtract 100000H from the address of the
  68.           first availabe location in extended memory and you'll have the
  69.           amount of extended memory already in use.  Subtract this number
  70.           from the total size of extended memory (gotten with int 15H,
  71.           function 88H), and you'll have the amount of space available.
  72.                Now that you know how much extended memory space is
  73.           available and where it begins, you're ready to use it. 
  74.           Unfortunately, all you can do is copy data into it or out of it. 
  75.           You can't directly access it.  To copy data to or from extended
  76.           memory you use interrupt 15H, function 87H.  You call function
  77.           87H by setting register AH to 87H, register CX to the number of
  78.           words to be moved (maximum of 32768 words), and setting ES:SI to
  79.           point to a Global Descriptor Table.
  80.                Now, Global Descriptor Tables are extremely important in
  81.           programming the 80286 in protected mode.  Here, they're just a
  82.           hassle, but it's something we have to go through in order to get
  83.           function 87H to work.  First, we have to set up a DESCRIPTOR.  A
  84.           DESCRIPTOR describes a segment of memory.  It's laid out like
  85.           this:
  86.  
  87.                Offset    # of Bytes     Description
  88.                  00          2            Maximum size of segment
  89.                  02          2            Low word of address of segment
  90.                  04          1            High byte of address
  91.                  05          1            Access rights byte
  92.                  06          2            Reserved (must be 00)
  93.  
  94.                The maximum size of the segment will always be less than or
  95.           equal to 65536, since that's the largest number of bytes we can
  96.           move at a time.  In the demonstration program it's set each time
  97.           to the number of bytes to actually be moved, but just leaving it
  98.           at 65536 would probably work as well.
  99.                Addresses in protected mode are 24 bits long.  They're
  100.           treated as a high byte and a low word.  So, for example, the
  101.           first byte of extended memory is at address 100000H, which splits
  102.           up into a high byte of 10H and a low byte of 0000H.  That's easy. 
  103.           To convert a DOS-style address (segment:offset), just use 16
  104.           times the segment plus the offset.  Strip off the low 8 bytes as
  105.           the low word, and the remaining 4 bytes as the high word.  For
  106.           example,  5EB4:002C becomes 5EB6C, having a high byte of 05H and
  107.           a low word of EB6CH.
  108.                For our purposes, the access rights byte will always be set
  109.           to 93H, and the reserved area will always be set to 0.
  110.                Now, to produce a GDT, we need six of these DESCRIPTORs.  Do
  111.           this by rote -- don't expect it to make a lot of sense.  They
  112.           should be laid out like this:
  113.  
  114.                Dummy Descriptor
  115.                GDT Descriptor
  116.                Source Descriptor
  117.                Target Descriptor
  118.                Code Segment Descriptor
  119.                Stack Segment Descriptor
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.                All those descriptors should be initialized to 0, except for
  127.           the Source Descriptor and the Target Descriptor.  The Source
  128.           Descriptor should be filled in with the appropriate data for the
  129.           block to be copied, and the Target Descriptor should be filled in
  130.           for the location to be copied to.
  131.                Once that's all done, just call interrupt 15H, function 87H. 
  132.           When it returns, if the Carry flag is cleared, the copy was
  133.           successful.
  134.                Now, isn't that simple?
  135.                Oh, one note concerning Turbo C and interrupt 15H: if you
  136.           try to access function 88H through int86() it will always return
  137.           with the carry flag set.  That's why the demonstration code uses
  138.           geninterrupt() instead of int86().
  139.                Concerning the code: the Pascal code will compile and run
  140.           under Turbo Pascal version 3.  The C code will compile and run
  141.           under Turbo C version 1.0.  The C code is broken up into separate
  142.           files as follows:
  143.  
  144.                xmemasm.c      contains the function 88H call.  Must be
  145.                               compiled under TCC, because it uses inline
  146.                               assembler code
  147.  
  148.                xmemcopy.c     contains the routine to copy blocks using
  149.                               interrupt 15H, function 88H
  150.  
  151.                xmemc.c        contains the rest of the support routines
  152.  
  153.                xmemtest.c     contains the main() program and the calls to
  154.                               the initialization routines
  155.  
  156.                xmemtest.prj   .PRJ file for xmemtest.
  157.  
  158.                To compile the C code, compile xmemasm.c with TCC.  Then use
  159.           TC and the project file xmemtest.prj to build xmemtest.exe.
  160.                The demonstration programs both do the same thing: they
  161.           check the system paramaters and give you some information on the
  162.           available extended memory.  Then they initialize a 16384 byte
  163.           buffer with recognizable data, copy the buffer into extended
  164.           memory, clear the buffer, copy the data back from extended memory
  165.           into the buffer, then check the data against the original data.
  166.  
  167.